package Utilities;

/*
 * Escala.java
 * Realizado por Paulo Chang, 11076
 *               Oscar Castañeda, 11086
 *               Francisco Martínez, 11096
 * Creado el 26 de agosto del 2011
 * Modificado por última vez el 31 de agosto del 2011
 * En esta clase se ejecuta el programa principal.
 */

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.Date;

/**
 * Principal
 * En esta clase se ejecuta el programa principal.
 * @author Francisco, Oscar, Paulo
 */
public class Principal {
    
    public static float prueba=10;
    public static ArrayList<Barco> listaBarcos = new ArrayList<Barco>(); //Lista que guarda a todos los barcos creados durante el programa.
    public static ArrayList<Puerto> listaPuertos = new ArrayList<Puerto>(); //Lista que guarda a todos los puertos creados durante el programa.
    public static ArrayList<Carga> listaCargas = new ArrayList<Carga>(); //Lista que guarda a todas las cargas creadas durante el programa.
    public static ArrayList<Contenedor> listaContenedores = new ArrayList<Contenedor>(); //Lista que guarda a todos los contenedores creados durante el programa.
    public static Scanner teclado = new Scanner(System.in); //Para ingreso de Strings.

    /**
     * Esta funcion sirve para ingresar números enteros positivos durante toda la ejecución del programa.
     * Verifica que lo que se ingresa sea un número entero positivo, si no lo es imprime un mensaje pidiendo que se 
     * vuelva a ingresar hasta que cumpla las condiciones. 
     * @return numero entero positivo.
     */
    public static int ingresarInt() {
        Integer numero = null;
        while (numero == null) {
            String num = teclado.nextLine();
            try {
                numero = Integer.parseInt(num);
            } catch (Exception e) {
                numero = null;
                System.out.print("Ingrese un número entero: ");
            }
        }
        return numero;
    }

    /**
     * Esta funcion sirve para ingresar números positivos durante toda la ejecución del programa.
     * Verifica que lo que se ingresa sea un número positivo, si no lo es imprime un mensaje pidiendo que se 
     * vuelva a ingresar hasta que cumpla las condiciones. 
     * @return numero float positivo.
     */
    public static float ingresarFloat() {
        Float numero = null;
        while (numero == null) {
            String num = teclado.nextLine();
            try {
                numero = Float.parseFloat(num);
            } catch (Exception e) {
                numero = null;
                System.out.print("Ingrese un número: ");
            }
        }
        return numero;
    }

    /**
     * Imprime la lista de puertos y pide al usuario que ingrese un número para elegir uno. Verifíca que el número
     * ingresado correspoda a una de las opciones
     * @param mensaje mensaje que se va a mostrar al pedir que se ingrese el número del puerto. 
     * @param puertoOrigen puerto de origen de la carga o barco, para evitar que se ingrese el mismo puerto. 
     * Si no hay restricciones con respecto a un puerto de origen, se ingresa null. 
     * @return puerto el puerto elegido por el usuario. 
     */
    public static Puerto elegirPuerto(String mensaje, Puerto puertoOrigen) {
        int idPuerto = 1;
        for (Puerto p : listaPuertos) {
            System.out.println(idPuerto + ") " + p.getNombre() + ", " + p.getPais());
            idPuerto++;
        }
        Puerto puertoDestino = null;
        do {
            System.out.print(mensaje);
            String numero = teclado.nextLine();
            try {
                int num = Integer.parseInt(numero);
                puertoDestino = listaPuertos.get(num - 1);
            } catch (Exception e) {
                System.out.println("Ingrese un número válido");
                puertoDestino = null;
            }
            if (puertoDestino == puertoOrigen && puertoDestino != null) {
                System.out.println("No puede elegir el mismo puerto de origen");
                puertoDestino = null;
            }
        } while (puertoDestino == null);
        return puertoDestino;
    }

    /**
     * Imprime la lista de barcos y pide al usuario que ingrese un número para elegir uno. Verifíca que el número
     * ingresado correspoda a una de las opciones
     * @param mensaje mensaje que se va a mostrar al pedir que se ingrese el número del barco.
     * @return barco el barco elegido por el usuario. 
     */
    public static Barco elegirBarco(String mensaje) {
        int idBarco = 1;
        for (Barco b : listaBarcos) {
            System.out.println(idBarco + ") " + b);
            idBarco++;
        }
        Barco barco = null;
        do {
            System.out.print(mensaje);
            String numero = teclado.nextLine();
            try {
                int num = Integer.parseInt(numero);
                barco = listaBarcos.get(num - 1);
            } catch (Exception e) {
                System.out.println("Ingrese un número válido");
                barco = null;
            }
        } while (barco == null);
        return barco;
    }

    /**
     * ingresoFecha
     * Permite al usuario ingresar los datos para una fecha y validarla.
     * @param estado String que puede contener la palabra "estimada" o "real", para diferenciar entre la petición de la fecha
     *               de llegada real de la petición de la fecha de llegada estimada.
     * @param fechaAnterior Instancia de la clase Date que es la fecha ingresada para el anterior puerto.
     * @return fecha Fecha ya validada para utilizar en el programa.
     */
    public static Date ingresoFecha(String estado, Date fechaAnterior) {
        int ano, mes, dia;
        Date fecha;
        do {
            do {
                System.out.println("Ingrese el año de la llegada " + estado + " del barco: ");
                ano = ingresarInt();
                if (ano < 1900) {
                    System.out.println("Debe de ingresar un año mayor o igual a 1900.");
                }
            } while (ano < 1900);
            do {
                System.out.println("Ingrese el número del mes de la llegada " + estado + " del barco: ");
                mes = ingresarInt();
                if ((mes < 1) || (mes > 13)) {
                    System.out.println("Debe de ingresar un número de mes entre 1 y 12.");
                }
            } while ((mes < 1) || (mes > 13));
            do {
                System.out.println("Ingrese el número del día de la llegada " + estado + " del barco: ");
                dia = ingresarInt();
                if ((dia < 1) || (dia > 31)) {
                    System.out.println("Debe de ingresar un número de día entre 1 y 31.");
                }
            } while ((dia < 1) || (dia > 31));
            ano = ano - 1900;
            mes = mes - 1;
            fecha = new Date(ano, mes, dia);
            if (fecha.before(fechaAnterior)) {
                System.out.println("Debe de ingresar una fecha posterior a la fecha de arribo " + estado + " del anterior puerto, que era de " + fechaAnterior);
            }
        } while (fecha.before(fechaAnterior));
        return fecha;
    }

    /**
     * crearBarco
     * Permite al usuario crear un nuevo barco, validando los datos ingresados por este.
     */
    public static void crearBarco() {
        System.out.println("***CREACIÓN DE UN NUEVO BARCO***");

        //Pedir los datos del barco
        float capacidadCarga;//Capacidad en toneladas del barco
        int capacidadContenedores; //Número de contenedores que puede llevar el barco.
        int ano, mes, dia; //Datos de la fecha estimada de llegada del barco a cada escala.
        int seleccionPuerto;//Puerto elegido para la escala en la siguiente ruta.
        String naviera, pais, capitan; //Datos que identifican al barco
        Ruta miRuta; //Ruta a seguir por el barco.
        boolean barcoValido; //Indica si el barco ingresado puede crearse porque no ha sido repetido.

        if (listaPuertos.size() < 2) {
            System.out.println("Antes de crear un barco, cree al menos dos puertos");
            return;
        }

        do {
            barcoValido = true;
            System.out.println("Ingrese el nombre de la compañía naviera dueña del barco: ");
            naviera = teclado.nextLine();
            System.out.println("Ingrese el país del cual es proveniente la compañía naviera: ");
            pais = teclado.nextLine();
            System.out.println("Ingrese el nombre del capitán encargado del barco: ");
            capitan = teclado.nextLine();
            if (!listaBarcos.isEmpty()) {
                for (Barco barco : listaBarcos) {
                    if ((barco.getNaviera().equals(naviera)) && (barco.getPais().equals(pais)) && (barco.getMiRuta().getCapitan().equals(capitan))) {
                        barcoValido = false;
                        System.out.println("Ha ingresado un barco que ya existía. Intente de nuevo.");
                    }
                }
            }
        } while (!barcoValido);

        do {
            System.out.println("Ingrese el número de toneladas métricas que puede llevar el barco: ");
            capacidadCarga = ingresarFloat();
        } while (capacidadCarga <= 0);
        do {
            System.out.println("Ingrese el número de contenedores que puede llevar el barco: ");
            capacidadContenedores = ingresarInt();
        } while (capacidadContenedores <= 0);

        //Creación de escalas
        Puerto puertoAnterior = null; //Índice del puerto anterior visitado, iniciando el conteo desde 1.
        Date fechaAnterior = new Date(0, 0, 0);
        Date fecha;
        ArrayList<Escala> escalas = new ArrayList<Escala>();

        System.out.println("De los siguientes puertos ");
        String seguir = "1";
        do {
            Puerto siguientePuerto = elegirPuerto("Ingrese el número correspondiente al siguiente puerto a colocar en la ruta de este barco:\n", puertoAnterior);
            fecha = ingresoFecha("estimada", fechaAnterior);
            Escala escala = new Escala(siguientePuerto, fecha);
            escalas.add(escala);
            fechaAnterior = fecha;
            puertoAnterior = siguientePuerto;
            System.out.print("Ingrese 0 para dejar de ingresar escalas en la ruta,\npresione cualquier otra tecla para continuar (debe ingresar al menos dos escalas):  ");
            seguir = teclado.nextLine();
        } while ((escalas.size() < 2) || (!seguir.equals("0")));

        //Creación de ruta
        miRuta = new Ruta(capitan, escalas);

        //Creación de barco
        Barco barco = new Barco(capacidadCarga, capacidadContenedores, naviera, pais, miRuta);

        //Agregación de barco a lista de Barcos
        listaBarcos.add(barco);
    }

    /**
     * registrarLlegadaBarco
     * Permite que el barco seleccionado por el usuario llegue al siguiente puerto sobre su ruta.
     * Asimismo, le permite al usuario ingresar la fecha de dicha llegada.
     * El barco llega al puerto, carga y descarga y se queda en dicho puerto hasta que llegue al siguiente.
     * Por tanto, el barco se almacena en la lista misBarcos del Puerto.
     */
    public static void registrarLlegadaBarco(Barco barco) {
        int numEscala;
        Escala escala;
        Date fechaLlegadaAnterior, fechaLlegadaActual;

        numEscala = barco.getMiRuta().getActualEscala();

        if (numEscala <= 0) {
            fechaLlegadaAnterior = new Date(0, 0, 0);
        } else {
            fechaLlegadaAnterior = barco.getMiRuta().getEscalas().get(numEscala - 1).getFechaReal();
        }
        fechaLlegadaActual = ingresoFecha("real", fechaLlegadaAnterior);
        boolean ocurrioArribo;
        ocurrioArribo = barco.arriboSiguientePuerto(fechaLlegadaActual);
        if (ocurrioArribo) {
            System.out.println("El barco elegido ha arribado al siguiente puerto, cargado, descargado y se encuentra anclado en dicho puerto.");
            escala = barco.getMiRuta().getEscalas().get(numEscala);
            escala.getPuerto().addBarco(barco);
            if (numEscala > 0) {
                escala = barco.getMiRuta().getEscalas().get(numEscala - 1);
                escala.getPuerto().removeBarco(barco);
            }
            if(numEscala+1==barco.getMiRuta().getEscalas().size()){
                barco.haFinalizadoRuta();
                System.out.println("El barco ha llegado al final de su ruta");
            }
        } else {
            barco.haFinalizadoRuta();
            System.out.println("El barco elegido ha llegado al final de su ruta, así que no puede arribar a ningún otro puerto.");
                
        }
    }
    
    public static boolean borrarBarco(Barco barco){
        int respuesta;
        do{        
            System.out.print("¿Desea borrarlo (sí=1, no=2)?: ");
            respuesta=ingresarInt();
        }while(respuesta!=1 && respuesta!=2);
        if(respuesta==1){
              listaBarcos.remove(barco);
              return true;
        }else
            return false;
    }
    
    /**
     * Pide toda la información necesaria para crear un puerto. Verifica que no se esté repitiendo
     * el barco que se está creando (que no tenga el mismo nombre y país que otra ya existente) y lo crea.
     * Lo agrega a la listaPuertos del programa.
     */
    public static void crearPuerto() {
        String nombre, pais, coordenadas;
        boolean introdujoPuertoValido = true;
        Puerto puertito = new Puerto("", "", "");

        do {
            introdujoPuertoValido = true;
            System.out.print("Por favor introduzca el nombre del puerto:");
            nombre = teclado.nextLine();
            System.out.print("Introduzca el país del puerto:");
            pais = teclado.nextLine();
            System.out.print("Introduzca sus coordenadas:");
            coordenadas = teclado.nextLine();

            puertito = new Puerto(nombre, pais, coordenadas);

            for (Puerto p : listaPuertos) {
                if (puertito.equals(p)) {
                    introdujoPuertoValido = false;
                    System.out.println("Ha introducido un puerto que ya existía");
                }
            }
        } while (!introdujoPuertoValido);

        listaPuertos.add(puertito);

    }

    /**
     * Sirve para crear puerto pero desde el GUI tentativo. 
     * @param nombre
     * @param pais
     * @param coordenadas
     * @return 
     */
    public static boolean crearPuerto(String nombre, String pais, String coordenadas) {
        Puerto puertito = new Puerto(nombre, pais, coordenadas);
        boolean introdujoPuertoValido = true;
        for (Puerto p : listaPuertos) {
            if (puertito.equals(p)) {
                introdujoPuertoValido = false;
            } else {
                listaPuertos.add(puertito);
            }
        }
        return introdujoPuertoValido;
    }

    /**
     * Sirve para crear una carga nueva, pide toda la información concerniente y verifica
     * que no tenga un nombre repetido, luego la crea. La carga creada es agregada a la listaCargas.
     * @param puertoOrigen el puerto de origen de la carga. 
     */
    public static void crearCarga(Puerto puertoOrigen) {

        if (listaPuertos.size() < 2) {
            System.out.println("Deben existir al menos dos Puertos para crear una carga.");
            return;
        }

        boolean cargaValida = true;
        String nombre = "";
        do {
            cargaValida = true;
            System.out.print("Introduzca el nombre de su carga: ");
            nombre = teclado.nextLine();

            if (listaCargas.size() > 0) {
                for (Carga laCarga : listaCargas) {
                    if (laCarga.getNombre().equals(nombre)) {
                        cargaValida = false;
                        System.out.println("Ya hay una carga con dicho nombre.");
                    }
                }
            }
        } while (!cargaValida);
        System.out.println("\nDe los puertos\n");
        Puerto destino = elegirPuerto("Introduzca el número del puerto destino\n"
                + "(No puede ir al puerto de donde sale)", puertoOrigen);
        float peso;
        do {
            System.out.print("Introduzca el peso de su carga: ");
            peso = ingresarFloat();
        } while (peso <= 0);

        System.out.print("Introduzca el nombre del dueño: ");
        String owner = teclado.nextLine();
        System.out.println("En una línea, escriba una descripción del producto");
        String descripcion = teclado.nextLine();

        Carga carga = new Carga(nombre, destino, puertoOrigen, peso, owner,
                descripcion);

        listaCargas.add(carga);
        puertoOrigen.agregar();


    }

    /**
     * Menú principal, tiene como opciones ir a los submenús Puertos y Barcos, o salir del programa. 
     * Pide que se ingrese una opción, verifica que sea válida y llama al método que la ejecute. 
     */
    public static void menuPrincipal() {
        boolean seRepite = true;
        while (seRepite) {
            System.out.println("**********MENÚ**********");
            System.out.println("1) Puertos");
            System.out.println("2) Barcos");
            System.out.println("3) Salir\n");
            int opcion;
            do {
                System.out.print("Su opción: ");
                opcion = ingresarInt();
            } while (opcion != 1 && opcion != 2 && opcion != 3);

            switch (opcion) {
                case 1:
                    menuPuertos();
                    break;
                case 2:
                    menuBarcos();
                    break;
                default:
                    seRepite = false;
            }
        }
    }

    /**
     * Este menú muestra opciones concernientes al funcionamiento de los puertos (crear uno, ver información
     * específica de uno), pide que se ingrese una opción, verifica que sea válida y llama al método
     * que la ejecute. 
     */
    public static void menuPuertos() {
        boolean repetir = true;
        do {
            System.out.println("**********MENÚ**********");
            System.out.println("1) Crear Puerto");
            System.out.println("2) Ver información de un puerto específico");
            System.out.println("3) Salir\n");
            int opcion;
            do {
                System.out.print("Su opción: ");
                opcion = ingresarInt();
            } while (opcion != 1 && opcion != 2 && opcion != 3);

            switch (opcion) {
                case 1:
                    crearPuerto();
                    break;
                case 2:
                    if (!listaPuertos.isEmpty()) {
                        menuPuertoDetalle();
                    } else {
                        System.out.println("Debe de crear por lo menos un puerto.");
                    }
                    break;
                default:
                   repetir = false;
            }
        } while (repetir);
    }

    /**
     * Primero pide que se elija de qué puerto se quiere ver la información, luego muestra
     * un menú con opciones concernientes al funcionamiento de cada puerto en específico, 
     * pide que se ingrese una opción, verifica que sea válida y llama al método
     * que la ejecute. 
     */
    public static void menuPuertoDetalle() {
        boolean repetir = true;
        System.out.println("**********PUERTOS**********");
        Puerto puerto = elegirPuerto("\nIntroduzca el número del puerto: ", null);
        do {
            System.out.println("*****MENÚ-" + puerto.getNombre() + ", " + puerto.getPais() + "*****");
            System.out.println("1) Ver Barcos en el Puerto");
            System.out.println("2) Ver Contenedores en el Puerto");
            System.out.println("3) Crear Carga");
            System.out.println("4) Consolidar Cargas");
            System.out.println("5) Ver dueños que esperan su carga en el puerto");
            System.out.println("6) Salir\n");
            int opcion;
            do {
                System.out.print("Su opción: ");
                opcion = ingresarInt();
            } while (opcion != 1 && opcion != 2 && opcion != 3 && opcion != 4 && opcion != 5 && opcion != 6);
            
            switch (opcion) {
                case 1:
                    if (!puerto.getBarcosEnPuerto().isEmpty()) {
                        int num = 1;
                        System.out.println("En este puerto se encuentran los siguientes barcos: ");
                        for (Barco barco : puerto.getBarcosEnPuerto()) {
                            System.out.println(num + ")" + barco);
                            num++;
                        }
                    } else {
                        System.out.println("No hay ningún barco en este puerto.");
                    }
                    break;
                case 2:
                    System.out.println(puerto);
                    break;
                case 3:
                    crearCarga(puerto);
                    System.out.println("Recuerde consolidar antes de que llegue un barco.");
                    break;
                case 4:
                    puerto.consolidar();
                    System.out.println("Se han consolidado las cargas del puerto.");
                    break;
                case 5:
                    imprimirDuenosCargas(puerto);
                    break;
                default:
                    if (!puerto.isConsolidado()) {
                        System.out.println("NO HA CONSOLIDADO\nConsolide sus cargas antes de salir");
                    } else {
                        repetir = false;
                    }
            }
        } while (repetir);
    }

    /**
     * Primero pide que se elija de qué barco se quiere ver la información, luego muestra
     * un menú con opciones concernientes al funcionamiento de cada barco en específico, 
     * pide que se ingrese una opción, verifica que sea válida y llama al método
     * que la ejecute. 
     */
    public static void menuBarcoDetalle() {
        boolean repetir = true;
        System.out.println("**********BARCOS**********");
        Barco barco = elegirBarco("Introduzca el número del barco: ");
        boolean borrado=false;
        if(barco.isFinalizadoRuta()){
          System.out.println("El barco ha llegado al final de su ruta");
          borrado=borrarBarco(barco);
        }
        if(!borrado){
        do {
            System.out.println("*****MENÚ-" + barco + "*****");
            System.out.println("1) Cantidad de contenedores con destino un Puerto específico");
            System.out.println("2) Ruta del barco");
            System.out.println("3) Arribo a siguiente puerto");
            System.out.println("4) Salir\n");
            int opcion;
            do {
                System.out.print("Su opción: ");
                opcion = ingresarInt();
            } while (opcion != 1 && opcion != 2 && opcion != 3 && opcion != 4);
                              
            Puerto puerto = null;
            if (opcion == 1) {
                puerto = elegirPuerto("\nIntroduzca el número del puerto: ", null);
            }
            switch (opcion) {
                case 1:
                    System.out.println("Hay " + barco.numContenedoresDestinadosA(puerto) + " contenedores"
                            + "destinados al puerto.");
                    break;
                case 2:
                    System.out.println(barco.contenedoresSegunRuta());
                    if(barco.isFinalizadoRuta()){
                        borrado=borrarBarco(barco);
                        if(borrado)
                            repetir=false;
                    }
                    break;
                case 3:
                    registrarLlegadaBarco(barco);
                    if(barco.isFinalizadoRuta()){
                       borrado=borrarBarco(barco);
                        if(borrado)
                            repetir=false;
                    }
                    break;
                default:
                    repetir = false;
            }
        } while (repetir);
        }
    }

    /**
     * Este menú muestra opciones concernientes al funcionamiento de los barcos (crear uno, ver información
    
     * específica de uno, ver cuáles están en un determinado puerto), pide que se ingrese una opción, 

     * verifica que sea válida y llama al método que la ejecute. 
     */
    public static void menuBarcos() {
        boolean repetir = true;
        do {
            System.out.println("**********MENÚ**********");
            System.out.println("1) Crear Barco");
            System.out.println("2) Información de un Barco en específico");
            System.out.println("3) Barcos Programados para llegar a un puerto");
            System.out.println("4) Salir\n");
            int opcion;
            do {
                System.out.print("Su opción: ");
                opcion = ingresarInt();
            } while (opcion != 1 && opcion != 2 && opcion != 3 && opcion != 4);

            switch (opcion) {
                case 1:
                    if (!listaPuertos.isEmpty()) {
                        crearBarco();
                    } else {
                        System.out.println("Debe de crear por lo menos un puerto antes de poder crear un barco.");
                    }
                    break;
                case 2:
                    if (!listaBarcos.isEmpty()) {
                        menuBarcoDetalle();
                    } else {
                        System.out.println("No se ha creado barco alguno");
                    }
                    break;
                case 3:
                    if ((!listaBarcos.isEmpty()) && (!listaPuertos.isEmpty())) {
                        barcosProgramadosParaPuerto();
                    } else {
                        System.out.println("Debe de crearse al menos un puerto y un barco para poder utilizar esta opción.");
                    }
                    break;
                default:
                    repetir = false;
            }
        } while (repetir);

    }

    /**
     * barcosProgramadosParaPuerto
     * Imprime una lista con los barcos dirigidos a cierto puerto.
     */
    public static void barcosProgramadosParaPuerto() {
        Date fechaMayor = new Date(0, 0, 0);
        Date fechaMenor = new Date(0, 0, 0);
        ArrayList<Barco> losBarcos = new ArrayList<Barco>();
        System.out.println("***BARCOS POR LLEGAR A UN PUERTO***");
        System.out.println("Elija uno de los puertos para conocer el listado de los barcos por llegar a él: ");
        Puerto puerto = elegirPuerto("Su opción: ", null);
        System.out.println("Ingrese la fecha que marca el inicio del intervalo de tiempo que desea consultar:");
        fechaMenor = ingresoFecha("estimada", fechaMayor);
        System.out.println("Ahora ingrese la fecha que marca el final del intervalo de tiempo a consultar:");
        fechaMayor = ingresoFecha("estimada", fechaMenor);
        losBarcos = arribosAPuerto(puerto, fechaMenor, fechaMayor);
        System.out.println("Barcos esperados en el puerto " + puerto.getNombre() + ", " + puerto.getPais() + " del " + fechaMenor + " al " + fechaMayor + ":");
        if (!losBarcos.isEmpty()) {
            int ordinal = 1;
            for (Barco barco : losBarcos) {
                System.out.println(ordinal + ") " + barco);
            }
        } else {
            System.out.println("No se espera a ningún barco en este puerto para el período de tiempo indicado.");
        }
    }

    /**
     * arribosAPuerto
     * Da la informacion sobre que barcos se esperan que arriben a un puerto en cierto intervalo de fechas.
     * @param puerto Puerto del cual se desea conocer la programación de arribos.
     * @param fechaMenor Límite inferior del intervalo del tiempo para el cual se desean conocer los arribos.
     * @param fechaMayor Límite superior del intervalo del tiempo para el cual se desean conocer los arribos.
     * @return barcosEsperados Colección de barcos que llegarán al puerto ingresado como parámetro entre los límites de tiempo indicados.
     */
    public static ArrayList<Barco> arribosAPuerto(Puerto puerto, Date fechaMenor, Date fechaMayor) {
        ArrayList<Puerto> puertosAVisitar = new ArrayList<Puerto>();
        ArrayList<Barco> barcosEsperados = new ArrayList<Barco>();
        for (Barco barco : listaBarcos) {
            puertosAVisitar = barco.getMiRuta().puertosPorVisitarDurante(fechaMenor, fechaMayor);
            for (Puerto posiblePuerto : puertosAVisitar) {
                if (posiblePuerto.equals(puerto)) {
                    barcosEsperados.add(barco);
                }
            }
        }
        return barcosEsperados;
    }

    /**
     * Imprime una lista de todos los dueños que esperan una carga en el puerto
     * que se ingresa como parámetro, indicando tanto el nombre de la carga como
     * del contenedor en el que viene. 
     * @param puertoDestino puerto en el que se encuentra el dueño. 
     */
    public static void imprimirDuenosCargas(Puerto puertoDestino) {
        int ordinalCarga = 1;
        boolean noIncluido = true;
        boolean incluirContenedor = true;
        if (!listaContenedores.isEmpty()) {
            for (Contenedor contenedor : listaContenedores) {
                if (contenedor.getPuertoDestino() == puertoDestino) {
                    incluirContenedor = true;
                    for (Contenedor contenedor2 : puertoDestino.getMisContenedores()) {
                        if (contenedor == contenedor2) {
                            incluirContenedor = false;
                        }
                    }
                    if (incluirContenedor) {
                        for (Carga carga : contenedor.getMisCargas()) {
                            System.out.println(carga.getOwner() + " espera " + carga.getNombre() + " del contenedor " + contenedor.getNombre());
                            noIncluido = false;
                        }
                    }
                }
            }
        }
        if (noIncluido) {
            System.out.println("Nadie espera cargas en este puerto");
        }
    }
    
    
    /**
     * Es el método que ejecuta todo el programa en sí. Para ello se ayuda de los demás
     * métodos. Primero pide que se ingrese el peso en toneladas de los contenedores
     * y luego muestra ya el menú principal. 
     * @param args 
     */
    public static void main(String[] args) {
        try {
            FileInputStream fIS = new FileInputStream("fsJBarcos.dat");
            ObjectInputStream os = new ObjectInputStream(fIS);
            listaBarcos = (ArrayList<Barco>) os.readObject();
            listaCargas = (ArrayList<Carga>) os.readObject();
            listaContenedores = (ArrayList<Contenedor>) os.readObject();
            listaPuertos = (ArrayList<Puerto>) os.readObject();
            Float capacidad; 
            capacidad = (Float) os.readObject();
            Contenedor.setCapacidad(capacidad);
            os.close();
        } catch (Exception ex) {                  
        float cargaMaxima;
       
        do {
            System.out.print("Introduzca la carga máxima de cada contenedor: ");
            cargaMaxima = ingresarFloat();
        } while (cargaMaxima <= 0);
        Contenedor.setCapacidad(cargaMaxima);
        }
        menuPrincipal();
           try {
            FileOutputStream fs = new FileOutputStream("fsJBarcos.dat");
            ObjectOutputStream os = new ObjectOutputStream(fs);
            os.writeObject(listaBarcos);
            os.writeObject(listaCargas);
            os.writeObject(listaContenedores);
            os.writeObject(listaPuertos);
            os.writeObject(new Float(Contenedor.getCapacidad()));
            os.close();
        } catch (Exception ex) {
            System.out.println("Lo sentimos: Hubo un error al intentar guardar sus archivos");
        }
    }
}
